package otheri.download;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import otheri.common.Utils;
import otheri.io.Input;
import otheri.io.Output;
import otheri.io.Serializable;

public class DownloadTask implements Serializable, Runnable {

	public static final int TAG_DOWNLOADING = 0;
	public static final int TAG_ERROR = 1;
	public static final int TAG_DELETED = 2;
	public static final int TAG_WAITING = 3;
	public static final int TAG_FINISHED = 4;

	protected int tag;
	protected String downloadUrl;
	protected String fileName;

	private DownloadManager manager;

	protected DownloadTask() {
	}

	protected DownloadTask(DownloadManager manager, String url, String fileName) {
		this();

		this.manager = manager;
		this.downloadUrl = url;
		this.fileName = fileName;

		this.tag = TAG_DOWNLOADING;
	}

	public void run() {
		int retry = 0;
		while (true) {
			try {
				HttpURLConnection conn = getDownloadConnection();
				InputStream is = conn.getInputStream();
				Input in = new Input(is);
				byte[] data = in.readAll();

				// 暂时只考虑了单线程不分片的情况，做完软件逻辑再一步一步做细节
				manager.saveTaskToFile(this, data);
				manager.onTaskFinished(this);
			} catch (Exception e) {
				// 稍后重试，重试n次后挂起
				Utils.println(e.toString());
				retry++;
				if (retry >= manager.getConfig().taskErrorRetryTimes) {
					// 挂起下载线程
					tag = TAG_ERROR;
					manager.onTaskError(this, e.toString());
					break;
				}
				try {
					Thread.sleep(manager.getConfig().taseErrorRetryWaitTime);
				} catch (Exception ee) {
					// 这里出异常，可以被归结为人品问题，爷不处理
				}
			}
		}
	}

	private HttpURLConnection getDownloadConnection() throws IOException {
		URL url = new URL(downloadUrl);
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		// 设置成GET方法
		conn.setDoOutput(false);
		conn.setRequestMethod("GET");
		// 设置超时（客户端仍需自己判断）
		conn.setReadTimeout(20000);
		conn.setConnectTimeout(20000);
		// 自动处理重定向
		conn.setInstanceFollowRedirects(true);
		return conn;
	}

	public void serialize(Output out) throws IOException {
		out.writeInt(tag);
		out.writeUTF8(downloadUrl);
		out.writeUTF8(fileName);
	}

	public void deserialize(Input in) throws IOException {
		tag = in.readInt();
		downloadUrl = in.readUTF8();
		fileName = in.readUTF8();
	}

}
